package behaviours;

import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.SequentialBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.SearchConstraints;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.util.leap.Iterator;

public class SubscribeAndListenBehaviour extends SequentialBehaviour {

	private String[] types;
	private Subscriber agent;
	
	public SubscribeAndListenBehaviour(Subscriber agent, String[] types) {
		this.agent = agent;
		this.types = types;
		initialize();
	}

	private void initialize() {
		for (int i = 0; i < types.length; i++) {
			addSubBehaviour(new SubscribeToDFBehaviour(types[i]));
		}
		addSubBehaviour(new ListenToSubscriptionsBehaviour());
	}
	
	private class SubscribeToDFBehaviour extends OneShotBehaviour {

		private final long MAX_SEARCH_RESULTS = 100;
		private String type;

		public SubscribeToDFBehaviour(String type) {
			this.type = type;
		}

		@Override
		public void action() {
			DFAgentDescription dfd = new DFAgentDescription();
			ServiceDescription sd = new ServiceDescription();
			sd.setType(type);
			dfd.addServices(sd);
			SearchConstraints sc = new SearchConstraints();
			sc.setMaxResults(MAX_SEARCH_RESULTS);
			myAgent.send(DFService.createSubscriptionMessage(myAgent,
					myAgent.getDefaultDF(), dfd, sc));
		}
	}
	
	private class ListenToSubscriptionsBehaviour extends CyclicBehaviour {
		
		@Override
		public void action() {
			ACLMessage msg = myAgent.receive(MessageTemplate.MatchSender(myAgent
					.getDefaultDF()));
			if (msg != null) {
				DFAgentDescription[] dfds;
				try {
					dfds = DFService.decodeNotification(msg
							.getContent());
					for (int i = 0; i < dfds.length; i++) {
						Iterator it = dfds[i].getAllServices();
						ServiceDescription sd = (ServiceDescription) it.next();
						String type = sd.getType();
						agent.updateSubscription(type, dfds[i].getName());
					}
				} catch (FIPAException e) {
					// Something went wrong
				}
			}
			else
				block();
		}
	}
}
